import cv2
import cv2 as cv
import numpy as np
import copy
from matplotlib import pyplot as plt
import sys

def base_func():
    img = cv.imread('01.png', cv.IMREAD_GRAYSCALE)
    img2 = cv.imread('01.png', cv.IMREAD_COLOR)
    print(np.shape(img))
    #cv.imshow("src",img)

    heigh = np.shape(img)[0]
    width = np.shape(img)[1]
#   channles = np.shape(img)[2]  #灰度图像没有颜色深度
    cv.imwrite("02.png", img)

    #图像二值化  cv2.THRESH_BINARY_INV 将二值图像黑白颠倒
    img_gray = cv2.adaptiveThreshold(
        img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 127, 1)
    cv.imwrite("03.png", img_gray)

   #腐蚀
    kernel = np.ones((5,5),np.uint8)
    erosion = cv.erode(img_gray,kernel,iterations = 1)
    cv.imwrite("04.png", erosion)

    #膨胀
    kernel = np.ones((5, 5), np.uint8)
    dilate = cv.dilate(img_gray,kernel,iterations = 1)
    cv.imwrite("05.png", dilate)

    #将白色设置为红色
    # thresh = cv.threshold(dilate, 255, 200, 0)
    # cv.imwrite("06.png", thresh)

    #查找指定特征轮廓
    contours, hierarchy=cv2.findContours(erosion, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    # cv.drawContours(img1, contours, -1, (0, 255, 0), 2)
    # cv.imwrite("06.png", img1)

    #检查图像获取目标轮廓
    contours  = check_contour(img, contours)

    draw_contours(img2, contours)

"""
对轮廓进行处理，检查符合条件的轮廓点位信息
"""
def check_contour(img, contours):
    primary_img = copy.deepcopy(img)

    for c in contours:
        if c is None:
            continue

        area = cv.contourArea(c)
        if area < 8000.0:
            continue


        #传入一个轮廓图像，返回 x y 是左上角的点， w和h是矩形边框的宽度和高度
        # 得到轮廓外接矩形大小
        x, y, w, h = cv.boundingRect(c)  # 这个函数就是用来返回值使用的。
        rade = w / h

        if 2.2 <= rade and rade <= 2.6:
            print("长宽比：" + str(rade))
            print("轮廓面积：" + str(area))
            # 绘制目标轮廓区域矩形
            cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1)  # 进行画图使用
            print("绿色目标区域:", x, y, w, h)
        else:
            continue

        """
        画出矩形
            img 是要画出轮廓的原图
            (x, y) 是左上角点的坐标
            (x+w, y+h) 是右下角的坐标
            0,255,0）是画线对应的rgb颜色
            2 是画出线的宽度
        """
        # 获得最小的矩形轮廓 可能带旋转角度
        rect = cv.minAreaRect(c)
        # 计算最小区域的坐标
        box = cv.boxPoints(rect)
        """
        坐标规范化为整数）
        box坐标顺序  左上  右上  右下  左下
        """
        box = np.intp(box)
        # 画出轮廓 BGR
        cv2.drawContours(img, [box], 0, (0, 0, 255), 3)

        font = cv.FONT_HERSHEY_PLAIN
        print("红色目标区域:" + str(box))

        list_src = []
        index = 1
        for point in box:
            list_src.append(point)
            cv.circle(img, point, 5, (0, 0, 255), -1)
            cv.putText(img, str(point) + "-" + str(index), point, font, 2, (0, 0, 255), 3, cv.LINE_AA)
            print("区域坐标顺序:" + str(point) + "-" + str(index))
            index += 1

        print(box[1][0], box[3][1])

        cv.imwrite("07.png", img)

        # 裁剪绘制出的矩形区域
        trim_rect = primary_img[y:y + h, x:x + w]

        return trim_rect

    return None



# 根据findContours返回的contours 画出轮廓
def draw_contours(img, contours):

    primary_img = copy.deepcopy(img)

    for c in contours:
        if c is None:
            continue

        area = cv.contourArea(c)

        if area < 8000.0:
            continue

        """
        传入一个轮廓图像，返回 x y 是左上角的点， w和h是矩形边框的宽度和高度
        """
        # 得到轮廓外接矩形大小
        x, y, w, h = cv.boundingRect(c)  # 这个函数就是用来返回值使用的。
        rade = w / h

        if 2.2 <= rade and rade <= 2.6:
            print("长宽比：" + str(rade))
            print("轮廓面积：" + str(area))
            # 绘制目标轮廓区域矩形
            cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1)  # 进行画图使用
            print("绿色目标区域:", x, y, w, h)
        else:
            continue

        """
        画出矩形
            img 是要画出轮廓的原图
            (x, y) 是左上角点的坐标
            (x+w, y+h) 是右下角的坐标
            0,255,0）是画线对应的rgb颜色
            2 是画出线的宽度
        """
        # 获得最小的矩形轮廓 可能带旋转角度
        rect = cv.minAreaRect(c)
        # 计算最小区域的坐标
        box = cv.boxPoints(rect)
        """
        坐标规范化为整数）
        box坐标顺序  左上  右上  右下  左下
        """
        box = np.intp(box)
        # 画出轮廓 BGR
        cv2.drawContours(img, [box], 0, (0, 0, 255), 3)

        font = cv.FONT_HERSHEY_PLAIN
        print("红色目标区域:"+str(box))

        list_src = []
        index = 1
        for point in box:
            list_src.append(point)
            cv.circle(img, point, 5, (0,0,255), -1)
            cv.putText(img, str(point)+"-"+str(index), point, font, 2, (0,0,255),3,cv.LINE_AA)
            print("区域坐标顺序:"+str(point)+"-"+str(index))
            index += 1

        print(box[1][0], box[3][1])

        cv.imwrite("07.png", img)

        #裁剪绘制出的矩形区域
        trim_rect = primary_img[y:y+h,x:x+w]
        #cv.imshow("目标区域",trim_rect)

        cv.imwrite("08.png", trim_rect)

        function_adjust(box, [h,w], list_src, trim_rect )

        return


def function_adjust(box, des_size, list_src, rect):

    img_rotate = cv.imread('08.png', cv.IMREAD_COLOR)
    cv.imwrite("09-1.png", rect)
    """
    #对图像做证正交投影
    源图像需要的坐标位置 左上 右上  左下  右下
    """
    h,w = des_size

    pts1 = np.float32([box[0], box[1], box[3], box[2]])
    pts2 = np.float32([[0, 0], [w, 0], [0, h], [w, h]])
    M = cv.getPerspectiveTransform(pts1, pts2)
    dst = cv.warpPerspective(img_rotate, M, (w, h))

    cv.imwrite("09.png", dst)

if __name__ == '__main__':
    base_func()
    cv.waitKey(0)
    cv.destroyAllWindows()



